{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### In-Place Concatenation and Repetition"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### In-Place Concatenation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We saw that using concatenation ended up creating a new sequence object:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2674852946824 [1, 2, 3, 4]\n",
      "2674852947208 [5, 6]\n"
     ]
    }
   ],
   "source": [
    "l1 = [1, 2, 3, 4]\n",
    "l2 = [5, 6]\n",
    "print(id(l1), l1)\n",
    "print(id(l2), l2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2674853399624 [1, 2, 3, 4, 5, 6]\n"
     ]
    }
   ],
   "source": [
    "l1 = l1 + l2\n",
    "print(id(l1), l1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But watch what happens when we use the in-place concatenation operator `+=:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2674853400520 [1, 2, 3, 4]\n",
      "2674852590920 [5, 6]\n"
     ]
    }
   ],
   "source": [
    "l1 = [1, 2, 3, 4]\n",
    "l2 = [5, 6]\n",
    "print(id(l1), l1)\n",
    "print(id(l2), l2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2674853400520 [1, 2, 3, 4, 5, 6]\n"
     ]
    }
   ],
   "source": [
    "l1 += l2\n",
    "print(id(l1), l1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice how the `id` of `l1` has **not** changed - it is the same object, just mutated!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "So far in this course I have often said that:\n",
    "\n",
    "`a = a + 1`\n",
    "\n",
    "and \n",
    "\n",
    "`a += 1`\n",
    "\n",
    "are the same thing.\n",
    "\n",
    "And for immutable objects such as integers, that is indeed true.\n",
    "\n",
    "But in fact `+` and `+=` are two different operators."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is interesting to note that the implementation of `+=` for lists will actually extend the list given any iterable, not just another list. This is really just the particular implementation of that operator for lists."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2674853566344 [1, 2, 3, 4]\n",
      "2674853559968 (5, 6, 7)\n"
     ]
    }
   ],
   "source": [
    "l1 = [1, 2, 3, 4]\n",
    "t1 = 5, 6, 7\n",
    "print(id(l1), l1)\n",
    "print(id(t1), t1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2674853566344 [1, 2, 3, 4, 5, 6, 7]\n"
     ]
    }
   ],
   "source": [
    "l1 += t1\n",
    "print(id(l1), l1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And this will work with other iterables as well:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2674853566344 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n"
     ]
    }
   ],
   "source": [
    "l1 += range(8, 11)\n",
    "print(id(l1), l1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "or even with iterable non-sequence types:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2674853566344 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]\n"
     ]
    }
   ],
   "source": [
    "l1 += {11, 12, 13}\n",
    "print(id(l1), l1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Of course, this will **not work** with **immutable** sequence types, such as tuples or strings:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2674852634768 (1, 2, 3)\n",
      "2674853559968 (4, 5, 6)\n"
     ]
    }
   ],
   "source": [
    "t1 = 1, 2, 3\n",
    "t2 = 4, 5, 6\n",
    "print(id(t1), t1)\n",
    "print(id(t2), t2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2674852634768 (1, 2, 3)\n"
     ]
    }
   ],
   "source": [
    "print(id(t1), t1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We cannot mutate an immutable container!\n",
    "What happens is that `+=` is not actually defined for the `tuple`, and so Python essentially executed this code:\n",
    "\n",
    "`t1 = t1 + t2`\n",
    "\n",
    "which, as we already know, always creates a new object."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "##### In-Place Repetition"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A similar result holds for in-place repetition.\n",
    "\n",
    "Let's see this using a list (mutable sequence type) first:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2674853567560 [1, 2, 3]\n"
     ]
    }
   ],
   "source": [
    "l = [1, 2, 3]\n",
    "print(id(l), l)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2674853567560 [1, 2, 3, 1, 2, 3]\n"
     ]
    }
   ],
   "source": [
    "l *= 2\n",
    "print(id(l), l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But obviously this operator will work differently if the sequence type is immutable:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2674853646840 (1, 2, 3)\n"
     ]
    }
   ],
   "source": [
    "t = (1, 2, 3)\n",
    "print(id(t), t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2674829349224 (1, 2, 3, 1, 2, 3)\n"
     ]
    }
   ],
   "source": [
    "t *= 2\n",
    "print(id(t), t)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
